package com.example.skillcinema.ui.screens.main.viewmodels

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.cachedIn
import com.example.skillcinema.adapters.FilmPagingSource
import com.example.skillcinema.db.displaymodels.FilmDisplayModel
import com.example.skillcinema.db.enums.FilmCollections
import com.example.skillcinema.db.enums.FilmFetchType
import com.example.skillcinema.db.repositories.BaseRepository.Companion.FIRST_PAGE
import com.example.skillcinema.db.repositories.BaseRepository.Companion.PREVIEW_ITEMS_COUNT
import com.example.skillcinema.db.repositories.FilmRepository
import com.example.skillcinema.extensions.sliceToPages
import dagger.hilt.android.lifecycle.HiltViewModel
import jakarta.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import java.time.LocalDate

@HiltViewModel
class FilmAllViewModel @Inject constructor(val repository: FilmRepository) : ViewModel() {
    private val _filmStateFlow: MutableStateFlow<List<FilmDisplayModel>> =
        MutableStateFlow<List<FilmDisplayModel>>(listOf())
    val filmPaged: Flow<PagingData<FilmDisplayModel>> = Pager(
        config = PagingConfig(PREVIEW_ITEMS_COUNT),
        pagingSourceFactory = { FilmPagingSource({ page -> getFilmData(page) }) }
    ).flow.cachedIn(viewModelScope)

    private val today = LocalDate.now()
    private val todayPlusTwoWeek = today.plusWeeks(2)

    lateinit var filters: Pair<Int, Int>
    lateinit var fetchType: FilmFetchType
    var filmId: Int = 0

    fun loadIt() {
        viewModelScope.launch {
            _filmStateFlow.value = getFilmData(FIRST_PAGE)
        }
    }

    private suspend fun getFilmData(page: Int): List<FilmDisplayModel> {
        return when (fetchType) {
            FilmFetchType.TOP_ALL -> {
                repository.getTopFilms(FilmCollections.TOP_POPULAR_ALL, page)
            }

            FilmFetchType.TOP_250 -> {
                repository.getTopFilms(FilmCollections.TOP_250_MOVIES, page)
            }

            FilmFetchType.SERIALS -> {
                repository.getSerials(page)
            }

            FilmFetchType.PREMIERS -> {
                repository.getPremiersFilms(todayPlusTwoWeek.year, todayPlusTwoWeek.month, page)
            }

            FilmFetchType.MIX_FILTERED -> {
                repository.getRandomFilteredFilms(filters.first, filters.second, page)
            }

            FilmFetchType.SIMILAR -> {
                if (page > FIRST_PAGE)
                    listOf<FilmDisplayModel>()
                else
                    repository.getSimilar(filmId)
            }

            FilmFetchType.STAFF_TOP_FILM -> {
                repository.getStaffBestFilms(filmId, page)
            }

            FilmFetchType.PROFILE_COLLECTION -> {
                if (filmId == -1) {
                    val res = repository.db.historyDao().getAllHistory().sliceToPages(page)
                    return if (res.isNotEmpty()) res.map { repository.getFilmById(it.elementId) } else listOf()
                } else
                    repository.db.filmCollectionCrossRefDao().getFilmsByCollectionId(filmId)
                        .sliceToPages(page).map { repository.getFilmById(it.filmId) }
            }
        }
    }
}